home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / hplip / ui4 / setupdialog.py < prev    next >
Text File  |  2009-10-09  |  47KB  |  1,288 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. # (c) Copyright 2001-2009 Hewlett-Packard Development Company, L.P.
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; either version 2 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program; if not, write to the Free Software
  17. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  18. #
  19. # Authors: Don Welch
  20. #
  21.  
  22. # StdLib
  23. import socket
  24. import operator
  25.  
  26. # Local
  27. from base.g import *
  28. from base import device, utils, models, pkit
  29. from prnt import cups
  30. from base.codes import *
  31. from ui_utils import *
  32. #from installer import core_install
  33. from installer.core_install import CoreInstall
  34.  
  35. # Qt
  36. from PyQt4.QtCore import *
  37. from PyQt4.QtGui import *
  38.  
  39. # Ui
  40. from setupdialog_base import Ui_Dialog
  41. from plugindialog import PluginDialog
  42. from wifisetupdialog import WifiSetupDialog, SUCCESS_CONNECTED
  43.  
  44. # Fax
  45. try:
  46.     from fax import fax
  47.     fax_import_ok = True
  48. except ImportError:
  49.     # This can fail on Python < 2.3 due to the datetime module
  50.     fax_import_ok = False
  51.     log.warning("Fax setup disabled - Python 2.3+ required.")
  52.  
  53.  
  54. PAGE_DISCOVERY = 0
  55. PAGE_DEVICES = 1
  56. PAGE_ADD_PRINTER = 2
  57. PAGE_REMOVE = 3
  58.  
  59.  
  60. BUTTON_NEXT = 0
  61. BUTTON_FINISH = 1
  62. BUTTON_ADD_PRINTER = 2
  63. BUTTON_REMOVE = 3
  64.  
  65. ADVANCED_SHOW = 0
  66. ADVANCED_HIDE = 1
  67.  
  68. DEVICE_DESC_ALL = 0
  69. DEVICE_DESC_SINGLE_FUNC = 1
  70. DEVICE_DESC_MULTI_FUNC = 2
  71.  
  72.  
  73.  
  74.  
  75.  
  76. class PasswordDialog(QDialog):
  77.     def __init__(self, prompt, parent=None, name=None, modal=0, fl=0):
  78.         QDialog.__init__(self, parent)
  79.         self.prompt = prompt
  80.  
  81.         Layout= QGridLayout(self)
  82.         Layout.setMargin(11)
  83.         Layout.setSpacing(6)
  84.  
  85.         self.PromptTextLabel = QLabel(self)
  86.         Layout.addWidget(self.PromptTextLabel,0,0,1,3)
  87.  
  88.         self.UsernameTextLabel = QLabel(self)
  89.         Layout.addWidget(self.UsernameTextLabel,1,0)
  90.  
  91.         self.UsernameLineEdit = QLineEdit(self)
  92.         self.UsernameLineEdit.setEchoMode(QLineEdit.Normal)
  93.         Layout.addWidget(self.UsernameLineEdit,1,1,1,2)
  94.  
  95.         self.PasswordTextLabel = QLabel(self)
  96.         Layout.addWidget(self.PasswordTextLabel,2,0)
  97.  
  98.         self.PasswordLineEdit = QLineEdit(self)
  99.         self.PasswordLineEdit.setEchoMode(QLineEdit.Password)
  100.         Layout.addWidget(self.PasswordLineEdit,2,1,1,2)
  101.  
  102.         self.OkPushButton = QPushButton(self)
  103.         Layout.addWidget(self.OkPushButton,3,2)
  104.  
  105.         self.languageChange()
  106.  
  107.         self.resize(QSize(420,163).expandedTo(self.minimumSizeHint()))
  108.  
  109.         self.connect(self.OkPushButton, SIGNAL("clicked()"), self.accept)
  110.         self.connect(self.PasswordLineEdit, SIGNAL("returnPressed()"), self.accept)
  111.  
  112.  
  113.     def getUsername(self):
  114.         return unicode(self.UsernameLineEdit.text())
  115.  
  116.  
  117.     def getPassword(self):
  118.         return unicode(self.PasswordLineEdit.text())
  119.  
  120.  
  121.     def languageChange(self):
  122.         self.setWindowTitle(self.__tr("HP Device Manager - Enter Username/Password"))
  123.         self.PromptTextLabel.setText(self.__tr(self.prompt))
  124.         self.UsernameTextLabel.setText(self.__tr("Username:"))
  125.         self.PasswordTextLabel.setText(self.__tr("Password:"))
  126.         self.OkPushButton.setText(self.__tr("OK"))
  127.  
  128.  
  129.     def __tr(self,s,c = None):
  130.         return qApp.translate("SetupDialog",s,c)
  131.  
  132.  
  133.  
  134. def showPasswordUI(prompt):
  135.     try:
  136.         dlg = PasswordDialog(prompt, None)
  137.  
  138.         if dlg.exec_() == QDialog.Accepted:
  139.             return (dlg.getUsername(), dlg.getPassword())
  140.  
  141.     finally:
  142.         pass
  143.  
  144.     return ("", "")
  145.  
  146.  
  147.  
  148. class DeviceTableWidgetItem(QTableWidgetItem):
  149.     def __init__(self, text, device_uri):
  150.         QTableWidgetItem.__init__(self, text, QTableWidgetItem.UserType)
  151.         self.device_uri = device_uri
  152.  
  153.  
  154.  
  155. class SetupDialog(QDialog, Ui_Dialog):
  156.     def __init__(self, parent, param, jd_port, device_uri=None, remove=False):
  157.         QDialog.__init__(self, parent)
  158.         self.setupUi(self)
  159.  
  160.         self.param = param
  161.         self.jd_port = jd_port
  162.         self.device_uri = device_uri
  163.         self.remove = remove
  164.  
  165.         if device_uri:
  166.             log.info("Using device: %s" % device_uri)
  167.  
  168.         self.initUi()
  169.  
  170.         if self.remove:
  171.             QTimer.singleShot(0, self.showRemovePage)
  172.         else:
  173.             if self.skip_discovery:
  174.                 QTimer.singleShot(0, self.showDevicesPage)
  175.             else:
  176.                 QTimer.singleShot(0, self.showDiscoveryPage)
  177.  
  178.         cups.setPasswordCallback(showPasswordUI)
  179.  
  180.  
  181.     #
  182.     # INIT
  183.     #
  184.  
  185.     def initUi(self):
  186.         self.setWindowIcon(QIcon(load_pixmap('hp_logo', '128x128')))
  187.  
  188.         # connect signals/slots
  189.         self.connect(self.CancelButton, SIGNAL("clicked()"), self.CancelButton_clicked)
  190.         self.connect(self.BackButton, SIGNAL("clicked()"), self.BackButton_clicked)
  191.         self.connect(self.NextButton, SIGNAL("clicked()"), self.NextButton_clicked)
  192.         self.connect(self.ManualGroupBox,  SIGNAL("clicked(bool)"),  self.ManualGroupBox_clicked)
  193.  
  194.         if self.remove:
  195.             self.initRemovePage()
  196.             self.max_page = 1
  197.         else:
  198.             self.initDiscoveryPage()
  199.             self.initDevicesPage()
  200.             self.initAddPrinterPage()
  201.             self.max_page = PAGE_ADD_PRINTER
  202.  
  203.     #
  204.     #  DISCOVERY PAGE
  205.     #
  206.  
  207.     def initDiscoveryPage(self):
  208.         self.UsbRadioButton.setChecked(True)
  209.         self.setUsbRadioButton(True)
  210.         self.ManualGroupBox.setChecked(False)
  211.  
  212.         self.advanced = False
  213.         self.manual = False
  214.         self.skip_discovery = False
  215.         self.NetworkRadioButton.setEnabled(prop.net_build)
  216.         self.WirelessButton.setEnabled(prop.net_build)
  217.         self.ParallelRadioButton.setEnabled(prop.par_build)
  218.         self.devices = {}
  219.         self.bus = 'usb'
  220.         self.timeout = 5
  221.         self.ttl = 4
  222.         self.search = ''
  223.         self.print_test_page = False
  224.         self.device_desc = DEVICE_DESC_ALL
  225.  
  226.         if self.param:
  227.             log.info("Searching for device...")
  228.             self.manual = True
  229.             self.advanced = True
  230.             self.ManualParamLineEdit.setText(self.param)
  231.             self.JetDirectSpinBox.setValue(self.jd_port)
  232.             self.ManualGroupBox.setChecked(True)
  233.             self.DiscoveryOptionsGroupBox.setEnabled(False)
  234.  
  235.             if self.manualDiscovery():
  236.                 self.skip_discovery = True
  237.             else:
  238.                 FailureUI(self, self.__tr("<b>Device not found.</b> <p>Please make sure your printer is properly connected and powered-on."))
  239.  
  240.                 match = device.usb_pat.match(self.param)
  241.                 if match is not None:
  242.                     self.UsbRadioButton.setChecked(True)
  243.                     self.setUsbRadioButton(True)
  244.  
  245.                 else:
  246.                     match = device.dev_pat.match(self.param)
  247.                     if match is not None and prop.par_build:
  248.                         self.ParallelRadioButton.setChecked(True)
  249.                         self.setParallelRadioButton(True)
  250.  
  251.                     else:
  252.                         match = device.ip_pat.match(self.param)
  253.                         if match is not None and prop.net_build:
  254.                             self.NetworkRadioButton.setChecked(True)
  255.                             self.setNetworkRadioButton(True)
  256.  
  257.                         else:
  258.                             FailureUI(self, self.__tr("<b>Invalid manual discovery parameter.</b>"))
  259.  
  260.         elif self.device_uri: # If device URI specified on the command line, skip discovery
  261.                               # if the device URI is well-formed (but not necessarily valid)
  262.             try:
  263.                 back_end, is_hp, self.bus, model, serial, dev_file, host, zc, port = \
  264.                 device.parseDeviceURI(self.device_uri)
  265.  
  266.             except Error:
  267.                 log.error("Invalid device URI specified: %s" % self.device_uri)
  268.  
  269.             else:
  270.                 name = host
  271.                 if self.bus == 'net':
  272.                     try:
  273.                         log.debug("Trying to get hostname for device...")
  274.                         name = socket.gethostbyaddr(host)[0]
  275.                     except socket.herror:
  276.                         log.debug("Failed.")
  277.                     else:
  278.                         log.debug("Host name=%s" % name)
  279.  
  280.                 self.devices = {self.device_uri : (model, model, name)}
  281.                 self.skip_discovery = True
  282.  
  283.         # If no network or parallel, usb is only option, skip initial page...
  284.         elif not prop.par_build and not prop.net_build:
  285.             self.skip_discovery = True
  286.             self.bus = 'usb'
  287.             self.UsbRadioButton.setChecked(True)
  288.             self.setUsbRadioButton(True)
  289.  
  290.         if prop.fax_build and prop.scan_build:
  291.             self.DeviceTypeComboBox.addItem("All devices/printers", QVariant(DEVICE_DESC_ALL))
  292.             self.DeviceTypeComboBox.addItem("Single function printers only", QVariant(DEVICE_DESC_SINGLE_FUNC))
  293.             self.DeviceTypeComboBox.addItem("All-in-one/MFP devices only", QVariant(DEVICE_DESC_MULTI_FUNC))
  294.         else:
  295.             self.DeviceTypeComboBox.setEnabled(False)
  296.  
  297.         self.connect(self.AdvancedButton, SIGNAL("clicked()"), self.AdvancedButton_clicked)
  298.         self.connect(self.UsbRadioButton, SIGNAL("toggled(bool)"), self.UsbRadioButton_toggled)
  299.         self.connect(self.NetworkRadioButton, SIGNAL("toggled(bool)"), self.NetworkRadioButton_toggled)
  300.         self.connect(self.WirelessButton, SIGNAL("toggled(bool)"), self.WirelessButton_toggled)
  301.         self.connect(self.ParallelRadioButton, SIGNAL("toggled(bool)"), self.ParallelRadioButton_toggled)
  302.         self.connect(self.NetworkTTLSpinBox,  SIGNAL("valueChanged(int)"), self.NetworkTTLSpinBox_valueChanged)
  303.         self.connect(self.NetworkTimeoutSpinBox,  SIGNAL("valueChanged(int)"),
  304.                      self.NetworkTimeoutSpinBox_valueChanged)
  305.         self.connect(self.ManualGroupBox,  SIGNAL("toggled(bool)"),  self.ManualGroupBox_toggled)
  306.  
  307.         self.showAdvanced()
  308.  
  309.  
  310.     def ManualGroupBox_toggled(self, checked):
  311.         self.DiscoveryOptionsGroupBox.setEnabled(not checked)
  312.  
  313.  
  314.     def manualDiscovery(self):
  315.         ret = False
  316.         # Validate param...
  317.         device_uri, sane_uri, fax_uri = device.makeURI(self.param, self.jd_port)
  318.  
  319.         if device_uri:
  320.             back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
  321.                 device.parseDeviceURI(device_uri)
  322.  
  323.             name = host
  324.             if bus == 'net':
  325.                 try:
  326.                     name = socket.gethostbyaddr(host)[0]
  327.                 except (socket.herror, socket.gaierror):
  328.                     pass
  329.  
  330.             self.devices = {device_uri : (model, model, name)}
  331.  
  332.             if bus == 'usb':
  333.                 self.UsbRadioButton.setChecked(True)
  334.                 self.setUsbRadioButton(True)
  335.  
  336.             elif bus == 'net' and prop.net_build:
  337.                 self.NetworkRadioButton.setChecked(True)
  338.                 self.setNetworkRadioButton(True)
  339.  
  340.             elif bus == 'par' and prop.par_build:
  341.                 self.ParallelRadioButton.setChecked(True)
  342.                 self.setParallelRadioButton(True)
  343.  
  344.             ret = True
  345.  
  346.         return ret
  347.  
  348.  
  349.     def ManualGroupBox_clicked(self, checked):
  350.         self.manual = checked
  351.         network = self.NetworkRadioButton.isChecked()
  352.         self.setJetDirect(network)
  353.  
  354.  
  355.     def showDiscoveryPage(self):
  356.         self.BackButton.setEnabled(False)
  357.         self.NextButton.setEnabled(True)
  358.         self.setNextButton(BUTTON_NEXT)
  359.         self.displayPage(PAGE_DISCOVERY)
  360.  
  361.  
  362.     def AdvancedButton_clicked(self):
  363.         self.advanced = not self.advanced
  364.         self.showAdvanced()
  365.  
  366.  
  367.     def showAdvanced(self):
  368.         if self.advanced:
  369.             self.AdvancedStackedWidget.setCurrentIndex(ADVANCED_SHOW)
  370.             self.AdvancedButton.setText(self.__tr("Hide Advanced Options"))
  371.             self.AdvancedButton.setIcon(QIcon(load_pixmap("minus", "16x16")))
  372.         else:
  373.             self.AdvancedStackedWidget.setCurrentIndex(ADVANCED_HIDE)
  374.             self.AdvancedButton.setText(self.__tr("Show Advanced Options"))
  375.             self.AdvancedButton.setIcon(QIcon(load_pixmap("plus", "16x16")))
  376.  
  377.  
  378.     def setJetDirect(self, enabled):
  379.         self.JetDirectLabel.setEnabled(enabled and self.manual)
  380.         self.JetDirectSpinBox.setEnabled(enabled and self.manual)
  381.  
  382.  
  383.     def setNetworkOptions(self,  enabled):
  384.         self.NetworkTimeoutLabel.setEnabled(enabled)
  385.         self.NetworkTimeoutSpinBox.setEnabled(enabled)
  386.         self.NetworkTTLLabel.setEnabled(enabled)
  387.         self.NetworkTTLSpinBox.setEnabled(enabled)
  388.  
  389.  
  390.     def setSearchOptions(self, enabled):
  391.         self.SearchLineEdit.setEnabled(enabled)
  392.         self.DeviceTypeComboBox.setEnabled(enabled)
  393.         self.DeviceTypeLabel.setEnabled(enabled)
  394.  
  395.  
  396.     def setManualDiscovery(self, enabled):
  397.         self.ManualGroupBox.setEnabled(enabled)
  398.  
  399.  
  400.     def setNetworkDiscovery(self, enabled):
  401.         self.NetworkDiscoveryMethodLabel.setEnabled(enabled)
  402.         self.NetworkDiscoveryMethodComboBox.setEnabled(enabled)
  403.         self.NetworkDiscoveryMethodComboBox.setCurrentIndex(1)
  404.  
  405.  
  406.     def UsbRadioButton_toggled(self, radio_enabled):
  407.         self.setUsbRadioButton(radio_enabled)
  408.  
  409.  
  410.     def setUsbRadioButton(self, checked):
  411.         self.setNetworkDiscovery(not checked)
  412.         self.setJetDirect(not checked)
  413.         self.setNetworkOptions(not checked)
  414.         self.setSearchOptions(checked)
  415.         self.setManualDiscovery(checked)
  416.  
  417.         if checked:
  418.             self.ManualParamLabel.setText(self.__tr("USB bus ID:device ID (bbb:ddd):"))
  419.             self.bus = 'usb'
  420.             # TODO: Set bbb:ddd validator
  421.  
  422.  
  423.     def NetworkRadioButton_toggled(self, radio_enabled):
  424.         self.setNetworkRadioButton(radio_enabled)
  425.  
  426.  
  427.     def setNetworkRadioButton(self, checked):
  428.         self.setNetworkDiscovery(checked)
  429.         self.setJetDirect(checked)
  430.         self.setNetworkOptions(checked)
  431.         self.setSearchOptions(checked)
  432.         self.setManualDiscovery(checked)
  433.  
  434.  
  435.         if checked:
  436.             self.ManualParamLabel.setText(self.__tr("IP Address or network name:"))
  437.             self.bus = 'net'
  438.             # TODO: Reset validator
  439.  
  440.     def WirelessButton_toggled(self, radio_enabled):
  441.         self.setWirelessButton(radio_enabled)
  442.  
  443.  
  444.     def setWirelessButton(self, checked):
  445.         self.setNetworkDiscovery(not checked)
  446.         self.setJetDirect(not checked)
  447.         self.setNetworkOptions(not checked)
  448.         self.setSearchOptions(not checked)
  449.         self.setManualDiscovery(not checked)
  450.  
  451.  
  452.         if checked:
  453.             self.ManualParamLabel.setText(self.__tr("IP Address or network name:"))
  454.             self.bus = 'net'
  455.  
  456.  
  457.     def ParallelRadioButton_toggled(self, radio_enabled):
  458.         self.setParallelRadioButton(radio_enabled)
  459.  
  460.  
  461.     def setParallelRadioButton(self, checked):
  462.         self.setNetworkDiscovery(not checked)
  463.         self.setJetDirect(not checked)
  464.         self.setNetworkOptions(not checked)
  465.         self.setSearchOptions(not checked)
  466.         self.setManualDiscovery(not checked)
  467.  
  468.  
  469.         if checked:
  470.             self.ManualParamLabel.setText(self.__tr("Device node (/dev/...):"))
  471.             self.bus = 'par'
  472.             # TODO: Set /dev/... validator
  473.  
  474.  
  475.     def NetworkTTLSpinBox_valueChanged(self, ttl):
  476.         self.ttl = ttl
  477.  
  478.  
  479.     def NetworkTimeoutSpinBox_valueChanged(self, timeout):
  480.         self.timeout = timeout
  481.  
  482.     #
  483.     # DEVICES PAGE
  484.     #
  485.  
  486.     def initDevicesPage(self):
  487.         self.connect(self.RefreshButton,  SIGNAL("clicked()"),  self.RefreshButton_clicked)
  488.  
  489.  
  490.     def showDevicesPage(self):
  491.         self.BackButton.setEnabled(True)
  492.         self.setNextButton(BUTTON_NEXT)
  493.         search = ""
  494.  
  495.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  496.         try:
  497.             if not self.devices:
  498.                 if self.manual and self.param: # manual, but not passed-in on command line
  499.                     self.manualDiscovery()
  500.  
  501.                 else: # probe
  502.                     net_search_type = ''
  503.  
  504.                     if self.bus == 'net':
  505.                         if self.discovery_method == 0:
  506.                             net_search_type = "slp"
  507.                         else:
  508.                             net_search_type = "mdns"
  509.  
  510.                         log.info("Searching... (bus=%s, timeout=%d, ttl=%d, search=%s desc=%d, method=%s)" %
  511.                                  (self.bus,  self.timeout, self.ttl, self.search or "(None)",
  512.                                   self.device_desc, net_search_type))
  513.                     else:
  514.                         log.info("Searching... (bus=%s, search=%s, desc=%d)" %
  515.                                  (self.bus,  self.search or "(None)", self.device_desc))
  516.  
  517.                     if self.device_desc == DEVICE_DESC_SINGLE_FUNC:
  518.                         filter_dict = {'scan-type' : (operator.le, SCAN_TYPE_NONE)}
  519.  
  520.                     elif self.device_desc == DEVICE_DESC_MULTI_FUNC:
  521.                         filter_dict = {'scan-type': (operator.gt, SCAN_TYPE_NONE)}
  522.  
  523.                     else: # DEVICE_DESC_ALL
  524.                         filter_dict = {}
  525.  
  526.                     self.devices = device.probeDevices([self.bus], self.timeout, self.ttl,
  527.                                                        filter_dict, self.search, net_search=net_search_type)
  528.         finally:
  529.             QApplication.restoreOverrideCursor()
  530.  
  531.         self.clearDevicesTable()
  532.  
  533.         if self.devices:
  534.             self.NextButton.setEnabled(True)
  535.             self.DevicesFoundIcon.setPixmap(load_pixmap('info', '16x16'))
  536.  
  537.             if len(self.devices) == 1:
  538.                 self.DevicesFoundLabel.setText(self.__tr("<b>1 device found.</b> Click <i>Next</i> to continue."))
  539.             else:
  540.                 self.DevicesFoundLabel.setText(self.__tr("<b>%1 devices found.</b> Select the device to install and click <i>Next</i> to continue.").arg(len(self.devices)))
  541.  
  542.             self.loadDevicesTable()
  543.  
  544.         else:
  545.             self.NextButton.setEnabled(False)
  546.             self.DevicesFoundIcon.setPixmap(load_pixmap('error', '16x16'))
  547.             log.error("No devices found on bus: %s" % self.bus)
  548.             self.DevicesFoundLabel.setText(self.__tr("<b>No devices found.</b><br>Click <i>Back</i> to change discovery options, or <i>Refresh</i> to search again."))
  549.  
  550.         self.displayPage(PAGE_DEVICES)
  551.  
  552.  
  553.     def loadDevicesTable(self):
  554.         self.DevicesTableWidget.setRowCount(len(self.devices))
  555.  
  556.         if self.bus == 'net':
  557.             if self.discovery_method == 0:
  558.                 headers = [self.__tr('Model'), self.__tr('IP Address'), self.__tr('Host Name'), self.__tr('Device URI')]
  559.                 device_uri_col = 3
  560.             else:
  561.                 headers = [self.__tr('Model'), self.__tr('Host Name'), self.__tr('Device URI')]
  562.                 device_uri_col = 2
  563.         else:
  564.             headers = [self.__tr('Model'), self.__tr('Device URI')]
  565.             device_uri_col = 1
  566.  
  567.         self.DevicesTableWidget.setColumnCount(len(headers))
  568.         self.DevicesTableWidget.setHorizontalHeaderLabels(headers)
  569.         flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
  570.  
  571.         for row, d in enumerate(self.devices):
  572.             back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(d)
  573.             model_ui = models.normalizeModelUIName(model)
  574.  
  575.             i = DeviceTableWidgetItem(QString(model_ui), d)
  576.             i.setFlags(flags)
  577.             self.DevicesTableWidget.setItem(row, 0, i)
  578.  
  579.             i = QTableWidgetItem(QString(d))
  580.             i.setFlags(flags)
  581.             self.DevicesTableWidget.setItem(row, device_uri_col, i)
  582.  
  583.             if self.bus == 'net':
  584.                 i = QTableWidgetItem(QString(host))
  585.                 i.setFlags(flags)
  586.                 self.DevicesTableWidget.setItem(row, 1, i)
  587.  
  588.                 if self.discovery_method == 0:
  589.                     i = QTableWidgetItem(QString(self.devices[d][2]))
  590.                     i.setFlags(flags)
  591.                     self.DevicesTableWidget.setItem(row, 2, i)
  592.  
  593.         self.DevicesTableWidget.resizeColumnsToContents()
  594.         self.DevicesTableWidget.selectRow(0)
  595.         self.DevicesTableWidget.setSortingEnabled(True)
  596.         self.DevicesTableWidget.sortItems(0)
  597.  
  598.  
  599.     def clearDevicesTable(self):
  600.         self.DevicesTableWidget.clear()
  601.         self.DevicesTableWidget.setRowCount(0)
  602.         self.DevicesTableWidget.setColumnCount(0)
  603.  
  604.  
  605.     def RefreshButton_clicked(self):
  606.         self.clearDevicesTable()
  607.         self.devices = []
  608.         QTimer.singleShot(0, self.showDevicesPage)
  609.  
  610.     #
  611.     # ADD PRINTER PAGE
  612.     #
  613.  
  614.     def initAddPrinterPage(self):
  615.         self.mq = {}
  616.  
  617.         self.connect(self.PrinterNameLineEdit, SIGNAL("textEdited(const QString &)"),
  618.                      self.PrinterNameLineEdit_textEdited)
  619.  
  620.         self.connect(self.FaxNameLineEdit, SIGNAL("textEdited(const QString &)"),
  621.                      self.FaxNameLineEdit_textEdited)
  622.  
  623.         self.PrinterNameLineEdit.setValidator(PrinterNameValidator(self.PrinterNameLineEdit))
  624.         self.FaxNameLineEdit.setValidator(PrinterNameValidator(self.FaxNameLineEdit))
  625.         self.FaxNumberLineEdit.setValidator(PhoneNumValidator(self.FaxNumberLineEdit))
  626.  
  627.         self.OtherPPDButton.setIcon(QIcon(load_pixmap('folder_open', '16x16')))
  628.         self.connect(self.OtherPPDButton, SIGNAL("clicked(bool)"), self.OtherPPDButton_clicked)
  629.  
  630.         self.OtherPPDButton.setToolTip(self.__tr("Browse for an alternative PPD file for this printer."))
  631.  
  632.         self.printer_fax_names_same = False
  633.         self.printer_name = ''
  634.         self.fax_name = ''
  635.         self.fax_setup_ok = True
  636.         self.fax_setup = False
  637.  
  638.  
  639.     def showAddPrinterPage(self):
  640.         # Install the plugin if needed...
  641.         core = CoreInstall()
  642.         plugin = self.mq.get('plugin', PLUGIN_NONE)
  643.         plugin_reason = self.mq.get('plugin-reason', PLUGIN_REASON_NONE)
  644.         if plugin > PLUGIN_NONE:
  645.  
  646.             if not core.check_for_plugin():
  647.                 ok, sudo_ok = pkit.run_plugin_command(plugin == PLUGIN_REQUIRED, plugin_reason)
  648.                 if not sudo_ok:
  649.                     FailureUI(self, self.__tr("<b>Unable to find an appropriate su/sudo utiltity to run hp-plugin.</b><p>Install kdesu, gnomesu, or gksu.</p>"))
  650.                     return
  651.                 if not ok or not core.check_for_plugin():
  652.                     if plugin == PLUGIN_REQUIRED:
  653.                         FailureUI(self, self.__tr("<b>The printer you are trying to setup requires a binary driver plug-in and it failed to install.</b><p>Please check your internet connection and try again.</p><p>Visit <u>http://hplipopensource.com</u> for more infomation.</p>"))
  654.                         return
  655.                     else:
  656.                         WarningUI(self, self.__tr("Either you have chosen to skip the installation of the optional plug-in or that installation has failed.  Your printer may not function at optimal performance."))
  657.  
  658.         self.setNextButton(BUTTON_ADD_PRINTER)
  659.  
  660.         if not self.printer_name:
  661.             self.setDefaultPrinterName()
  662.  
  663.         self.findPrinterPPD()
  664.  
  665.         if fax_import_ok and prop.fax_build and \
  666.             self.mq.get('fax-type', FAX_TYPE_NONE) not in (FAX_TYPE_NONE, FAX_TYPE_NOT_SUPPORTED):
  667.  
  668.             self.fax_setup = True
  669.             self.SetupFaxGroupBox.setChecked(True)
  670.             self.SetupFaxGroupBox.setEnabled(True)
  671.  
  672.             if not self.fax_name:
  673.                 self.setDefaultFaxName()
  674.  
  675.             self.findFaxPPD()
  676.  
  677.             self.readwriteFaxInformation()
  678.  
  679.         else:
  680.             self.SetupFaxGroupBox.setChecked(False)
  681.             self.SetupFaxGroupBox.setEnabled(False)
  682.             self.fax_name = ''
  683.             self.fax_name_ok = True
  684.             self.fax_setup = False
  685.             self.fax_setup_ok = True
  686.  
  687.         self.updatePPD()
  688.         self.setAddPrinterButton()
  689.         self.displayPage(PAGE_ADD_PRINTER)
  690.  
  691.  
  692.  
  693.  
  694.     def updatePPD(self):
  695.         if self.print_ppd is None:
  696.             log.error("No appropriate print PPD file found for model %s" % self.model)
  697.             self.PPDFileLineEdit.setText(self.__tr('(Not found. Click browse button to select a PPD file.)'))
  698.             try:
  699.                 self.PPDFileLineEdit.setStyleSheet("background-color: yellow")
  700.             except AttributeError:
  701.                 pass
  702.             self.PrinterDescriptionLineEdit.setText(QString(""))
  703.  
  704.         else:
  705.             self.PPDFileLineEdit.setText(self.print_ppd[0])
  706.             self.PrinterDescriptionLineEdit.setText(self.print_ppd[1])
  707.             try:
  708.                 self.PPDFileLineEdit.setStyleSheet("")
  709.             except AttributeError:
  710.                 pass
  711.  
  712.  
  713.     def OtherPPDButton_clicked(self, b):
  714.         ppd_file = unicode(QFileDialog.getOpenFileName(self, self.__tr("Select PPD File"),
  715.                                                        sys_conf.get('dirs', 'ppd'),
  716.                                                        self.__tr("PPD Files (*.ppd *.ppd.gz);;All Files (*)")))
  717.  
  718.         if ppd_file and os.path.exists(ppd_file):
  719.             self.print_ppd = (ppd_file, cups.getPPDDescription(ppd_file))
  720.             self.updatePPD()
  721.             self.setAddPrinterButton()
  722.  
  723.  
  724.     def findPrinterPPD(self):
  725.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  726.         try:
  727.             self.print_ppd = None
  728.             self.ppds = cups.getSystemPPDs()
  729.             model = cups.stripModel2(self.model)
  730.             self.print_ppd = cups.getPPDFile2(model, self.ppds)
  731.         finally:
  732.             QApplication.restoreOverrideCursor()
  733.  
  734.  
  735.     def findFaxPPD(self):
  736.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  737.         try:
  738.             log.debug("Searching for fax PPD for model %s" % self.model)
  739.  
  740.             if prop.hpcups_build:
  741.                 if self.mq.get('fax-type', FAX_TYPE_NONE) == FAX_TYPE_SOAP:
  742.                     fax_ppd_name = "HP-Fax2-hpcups" # Fixed width (2528 pixels) and 300dpi rendering
  743.                     nick = "HP Fax2 hpcups"
  744.                 else:
  745.                     fax_ppd_name = "HP-Fax-hpcups" # Standard
  746.                     nick = "HP Fax hpcups"
  747.  
  748.             else: # hpijs
  749.                 if self.mq.get('fax-type', FAX_TYPE_NONE) == FAX_TYPE_SOAP:
  750.                     fax_ppd_name = "HP-Fax2-hpijs" # Fixed width (2528 pixels) and 300dpi rendering
  751.                     nick = "HP Fax2 hpijs"
  752.                 else:
  753.                     fax_ppd_name = "HP-Fax-hpijs" # Standard
  754.                     nick = "HP Fax hpijs"
  755.  
  756.             ppds = []
  757.  
  758.             for f in utils.walkFiles(sys_conf.get('dirs', 'ppd'), pattern="HP-Fax*.ppd*", abs_paths=True):
  759.                 ppds.append(f)
  760.  
  761.             for f in ppds:
  762.                 if f.find(fax_ppd_name) >= 0 and cups.getPPDDescription(f) == nick:
  763.                     self.fax_ppd = f
  764.                     self.fax_setup_ok = True
  765.                     log.debug("Found fax PPD: %s" % f)
  766.                     break
  767.             else:
  768.                 self.fax_ppd = None
  769.                 self.fax_setup_ok = False
  770.                 FailureUI(self, self.__tr("<b>Unable to locate the HPLIP Fax PPD file:</b><p>%1.ppd.gz</p><p>Fax setup has been disabled.").arg(fax_ppd_name))
  771.                 self.fax_setup = False
  772.                 self.SetupFaxGroupBox.setChecked(False)
  773.                 self.SetupFaxGroupBox.setEnabled(False)
  774.  
  775.         finally:
  776.             QApplication.restoreOverrideCursor()
  777.  
  778.  
  779.  
  780.     def setDefaultPrinterName(self):
  781.         self.installed_print_devices = device.getSupportedCUPSDevices(['hp'])
  782.         log.debug(self.installed_print_devices)
  783.  
  784.         self.installed_queues = [p.name for p in cups.getPrinters()]
  785.  
  786.         back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.device_uri)
  787.         default_model = utils.xstrip(model.replace('series', '').replace('Series', ''), '_')
  788.  
  789.         printer_name = default_model
  790.  
  791.         # Check for duplicate names
  792.         if self.device_uri in self.installed_print_devices and \
  793.             printer_name in self.installed_print_devices[self.device_uri]:
  794.                 i = 2
  795.                 while True:
  796.                     t = printer_name + "_%d" % i
  797.                     if t not in self.installed_print_devices[self.device_uri]:
  798.                         printer_name += "_%d" % i
  799.                         break
  800.                     i += 1
  801.  
  802.         self.printer_name_ok = True
  803.         self.PrinterNameLineEdit.setText(printer_name)
  804.         log.debug(printer_name)
  805.         self.printer_name = printer_name
  806.  
  807.  
  808.     def setDefaultFaxName(self):
  809.         self.installed_fax_devices = device.getSupportedCUPSDevices(['hpfax'])
  810.         log.debug(self.installed_fax_devices)
  811.  
  812.         self.fax_uri = self.device_uri.replace('hp:', 'hpfax:')
  813.  
  814.         back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.fax_uri)
  815.         default_model = utils.xstrip(model.replace('series', '').replace('Series', ''), '_')
  816.  
  817.         fax_name = default_model + "_fax"
  818.  
  819.         # Check for duplicate names
  820.         if self.fax_uri in self.installed_fax_devices and \
  821.             fax_name in self.installed_fax_devices[self.fax_uri]:
  822.                 i = 2
  823.                 while True:
  824.                     t = fax_name + "_%d" % i
  825.                     if t not in self.installed_fax_devices[self.fax_uri]:
  826.                         fax_name += "_%d" % i
  827.                         break
  828.                     i += 1
  829.  
  830.         self.fax_name_ok = True
  831.         self.FaxNameLineEdit.setText(fax_name)
  832.         self.fax_name = fax_name
  833.  
  834.  
  835.     def PrinterNameLineEdit_textEdited(self, t):
  836.         self.printer_name = unicode(t)
  837.         self.printer_name_ok = True
  838.  
  839.         if not self.printer_name:
  840.             self.PrinterNameLineEdit.setToolTip(self.__tr('You must enter a name for the printer.'))
  841.             self.printer_name_ok = False
  842.  
  843.         elif self.fax_name == self.printer_name:
  844.             s = self.__tr('The printer name and fax name must be different. Please choose different names.')
  845.             self.PrinterNameLineEdit.setToolTip(s)
  846.             self.FaxNameLineEdit.setToolTip(s)
  847.             self.fax_name_ok = False
  848.             self.printer_name_ok = False
  849.             self.printer_fax_names_same = True
  850.  
  851.         elif self.printer_name in self.installed_queues:
  852.             self.PrinterNameLineEdit.setToolTip(self.__tr('A printer already exists with this name. Please choose a different name.'))
  853.             self.printer_name_ok = False
  854.  
  855.         elif self.printer_fax_names_same:
  856.             if self.fax_name != self.printer_name:
  857.                 self.printer_fax_names_same = False
  858.                 self.printer_name_ok = True
  859.  
  860.                 self.FaxNameLineEdit.emit(SIGNAL("textChanged(const QString &)"),
  861.                             (self.FaxNameLineEdit.text(),))
  862.  
  863.         self.setIndicators()
  864.         self.setAddPrinterButton()
  865.  
  866.  
  867.     def FaxNameLineEdit_textEdited(self, t):
  868.         self.fax_name = unicode(t)
  869.         self.fax_name_ok = True
  870.  
  871.         if not self.fax_name:
  872.             self.FaxNameLineEdit.setToolTip(self.__tr('You must enter a fax name.'))
  873.             self.fax_name_ok = False
  874.  
  875.         elif self.fax_name == self.printer_name:
  876.             s = self.__tr('The printer name and fax name must be different. Please choose different names.')
  877.             self.PrinterNameLineEdit.setToolTip(s)
  878.             self.FaxNameLineEdit.setToolTip(s)
  879.             self.printer_name_ok = False
  880.             self.fax_name_ok = False
  881.             self.printer_fax_names_same = True
  882.  
  883.         elif self.fax_name in self.installed_queues:
  884.             self.FaxNameLineEdit.setToolTip(self.__tr('A fax already exists with this name. Please choose a different name.'))
  885.             self.fax_name_ok = False
  886.  
  887.         elif self.printer_fax_names_same:
  888.             if self.fax_name != self.printer_name:
  889.                 self.printer_fax_names_same = False
  890.                 self.fax_name_ok = True
  891.  
  892.                 self.PrinterNameLineEdit.emit(SIGNAL("textChanged(const QString&)"),
  893.                             (self.PrinterNameLineEdit.text(),))
  894.  
  895.         self.setIndicators()
  896.         self.setAddPrinterButton()
  897.  
  898.  
  899.     def setIndicators(self):
  900.         if self.printer_name_ok:
  901.             self.PrinterNameLineEdit.setToolTip(QString(""))
  902.             try:
  903.                 self.PrinterNameLineEdit.setStyleSheet("")
  904.             except AttributeError:
  905.                 pass
  906.         else:
  907.             try:
  908.                 self.PrinterNameLineEdit.setStyleSheet("background-color: yellow")
  909.             except AttributeError:
  910.                 pass
  911.  
  912.         if self.fax_name_ok:
  913.             self.FaxNameLineEdit.setToolTip(QString(""))
  914.             try:
  915.                 self.PrinterNameLineEdit.setStyleSheet("")
  916.             except AttributeError:
  917.                 pass
  918.         else:
  919.             try:
  920.                 self.PrinterNameLineEdit.setStyleSheet("background-color: yellow")
  921.             except AttributeError:
  922.                 pass
  923.  
  924.  
  925.     def setAddPrinterButton(self):
  926.         self.NextButton.setEnabled((self.printer_name_ok and self.print_ppd is not None) and
  927.                                    ((self.fax_setup and self.fax_name_ok) or not self.fax_setup))
  928.  
  929.  
  930.     #
  931.     # ADD PRINTER
  932.     #
  933.  
  934.     def addPrinter(self):
  935.         self.setupPrinter()
  936.  
  937.         if self.fax_setup:
  938.             self.setupFax()
  939.             self.readwriteFaxInformation(False)
  940.  
  941.         if self.print_test_page:
  942.             self.printTestPage()
  943.  
  944.         self.close()
  945.  
  946.  
  947.  
  948.     #
  949.     # SETUP PRINTER/FAX
  950.     #
  951.  
  952.     def setupPrinter(self):
  953.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  954.         try:
  955.             cups.setPasswordPrompt("You do not have permission to add a printer.")
  956.             if not os.path.exists(self.print_ppd[0]): # assume foomatic: or some such
  957.                 status, status_str = cups.addPrinter(self.printer_name.encode('utf8'), self.device_uri,
  958.                     self.print_location, '', self.print_ppd[0], self.print_desc)
  959.             else:
  960.                 status, status_str = cups.addPrinter(self.printer_name.encode('utf8'), self.device_uri,
  961.                     self.print_location, self.print_ppd[0], '', self.print_desc)
  962.  
  963.             log.debug("addPrinter() returned (%d, %s)" % (status, status_str))
  964.             self.installed_print_devices = device.getSupportedCUPSDevices(['hp'])
  965.  
  966.             log.debug(self.installed_print_devices)
  967.  
  968.             if self.device_uri not in self.installed_print_devices or \
  969.                 self.printer_name not in self.installed_print_devices[self.device_uri]:
  970.  
  971.                 QApplication.restoreOverrideCursor()
  972.                 FailureUI(self, self.__tr("<b>Printer queue setup failed.</b><p>Please restart CUPS and try again."))
  973.             else:
  974.                 # TODO:
  975.                 #service.sendEvent(self.hpssd_sock, EVENT_CUPS_QUEUES_CHANGED, device_uri=self.device_uri)
  976.                 pass
  977.  
  978.         finally:
  979.             QApplication.restoreOverrideCursor()
  980.  
  981.  
  982.     def setupFax(self):
  983.         QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  984.         try:
  985.             cups.setPasswordPrompt("You do not have permission to add a fax device.")
  986.             if not os.path.exists(self.fax_ppd):
  987.                 status, status_str = cups.addPrinter(self.fax_name.encode('utf8'),
  988.                     self.fax_uri, self.fax_location, '', self.fax_ppd,  self.fax_desc)
  989.             else:
  990.                 status, status_str = cups.addPrinter(self.fax_name.encode('utf8'),
  991.                     self.fax_uri, self.fax_location, self.fax_ppd, '', self.fax_desc)
  992.  
  993.             log.debug("addPrinter() returned (%d, %s)" % (status, status_str))
  994.             self.installed_fax_devices = device.getSupportedCUPSDevices(['hpfax'])
  995.  
  996.             log.debug(self.installed_fax_devices)
  997.  
  998.             if self.fax_uri not in self.installed_fax_devices or \
  999.                 self.fax_name not in self.installed_fax_devices[self.fax_uri]:
  1000.  
  1001.                 QApplication.restoreOverrideCursor()
  1002.                 FailureUI(self, self.__tr("<b>Fax queue setup failed.</b><p>Please restart CUPS and try again."))
  1003.             else:
  1004.                 pass
  1005.                 # TODO:
  1006.                 #service.sendEvent(self.hpssd_sock, EVENT_CUPS_QUEUES_CHANGED, device_uri=self.fax_uri)
  1007.  
  1008.         finally:
  1009.             QApplication.restoreOverrideCursor()
  1010.  
  1011.  
  1012.     def readwriteFaxInformation(self, read=True):
  1013.         try:
  1014.             QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
  1015.  
  1016.             d = fax.getFaxDevice(self.fax_uri, disable_dbus=True)
  1017.  
  1018.             while True:
  1019.                 try:
  1020.                     d.open()
  1021.                 except Error:
  1022.                     error_text = self.__tr("Unable to communicate with the device. Please check the device and try again.")
  1023.                     log.error(unicode(error_text))
  1024.                     if QMessageBox.critical(self,
  1025.                                            self.windowTitle(),
  1026.                                            error_text,
  1027.                                            QMessageBox.Retry | QMessageBox.Default,
  1028.                                            QMessageBox.Cancel | QMessageBox.Escape,
  1029.                                            QMessageBox.NoButton) == QMessageBox.Cancel:
  1030.                         break
  1031.  
  1032.                 else:
  1033.                     try:
  1034.                         tries = 0
  1035.                         ok = True
  1036.  
  1037.                         while True:
  1038.                             tries += 1
  1039.  
  1040.                             try:
  1041.                                 if read:
  1042.                                     self.fax_number = unicode(d.getPhoneNum())
  1043.                                     self.fax_name_company = unicode(d.getStationName())
  1044.                                 else:
  1045.                                     d.setStationName(self.fax_name_company)
  1046.                                     d.setPhoneNum(self.fax_number)
  1047.  
  1048.                             except Error:
  1049.                                 error_text = self.__tr("<b>Device I/O Error</b><p>Could not communicate with device. Device may be busy.")
  1050.                                 log.error(unicode(error_text))
  1051.  
  1052.                                 if QMessageBox.critical(self,
  1053.                                                        self.windowTitle(),
  1054.                                                        error_text,
  1055.                                                        QMessageBox.Retry | QMessageBox.Default,
  1056.                                                        QMessageBox.Cancel | QMessageBox.Escape,
  1057.                                                        QMessageBox.NoButton) == QMessageBox.Cancel:
  1058.                                     break
  1059.  
  1060.  
  1061.                                 time.sleep(5)
  1062.                                 ok = False
  1063.  
  1064.                                 if tries > 12:
  1065.                                     break
  1066.  
  1067.                             else:
  1068.                                 ok = True
  1069.                                 break
  1070.  
  1071.                     finally:
  1072.                         d.close()
  1073.  
  1074.                     if ok and read:
  1075.                         self.FaxNumberLineEdit.setText(self.fax_number)
  1076.                         self.NameCompanyLineEdit.setText(self.fax_name_company)
  1077.  
  1078.                     break
  1079.  
  1080.         finally:
  1081.             QApplication.restoreOverrideCursor()
  1082.  
  1083.  
  1084.     def printTestPage(self):
  1085.         try:
  1086.             d = device.Device(self.device_uri)
  1087.         except Error, e:
  1088.             FailureUI(self, self.__tr("<b>Device error:</b><p>%s (%s)." % (e.msg, e.opt)))
  1089.  
  1090.         else:
  1091.             try:
  1092.                 d.open()
  1093.             except Error:
  1094.                 FailureUI(self, self.__tr("<b>Unable to print to printer.</b><p>Please check device and try again."))
  1095.             else:
  1096.                 if d.isIdleAndNoError():
  1097.                     d.close()
  1098.  
  1099.                     try:
  1100.                         d.printTestPage(self.printer_name)
  1101.                     except Error, e:
  1102.                         if e.opt == ERROR_NO_CUPS_QUEUE_FOUND_FOR_DEVICE:
  1103.                             FailureUI(self, self.__tr("<b>No CUPS queue found for device.</b><p>Please install the printer in CUPS and try again."))
  1104.                         else:
  1105.                             FailureUI(self, self.__tr("<b>Printer Error</b><p>An error occured: %s (code=%d)." % (e.msg, e.opt)))
  1106.                 else:
  1107.                     FailureUI(self, self.__tr("<b>Printer Error.</b><p>Printer is busy, offline, or in an error state. Please check the device and try again."))
  1108.                     d.close()
  1109.  
  1110.     #
  1111.     # Remove Page
  1112.     #
  1113.  
  1114.     def initRemovePage(self):
  1115.         pass
  1116.  
  1117.  
  1118.     def showRemovePage(self):
  1119.         self.displayPage(PAGE_REMOVE)
  1120.         self.StepText.setText(self.__tr("Step 1 of 1"))
  1121.         self.setNextButton(BUTTON_REMOVE)
  1122.         self.BackButton.setEnabled(False)
  1123.         self.NextButton.setEnabled(False)
  1124.  
  1125.         self.RemoveDevicesTableWidget.verticalHeader().hide()
  1126.  
  1127.         self.installed_printers = device.getSupportedCUPSPrinters(['hp', 'hpfax'])
  1128.         log.debug(self.installed_printers)
  1129.  
  1130.         if not self.installed_printers:
  1131.             FailureUI(self, self.__tr("<b>No printers or faxes found to remove.</b><p>You must setup a least one printer or fax before you can remove it."))
  1132.             self.close()
  1133.             return
  1134.  
  1135.         self.RemoveDevicesTableWidget.setRowCount(len(self.installed_printers))
  1136.  
  1137.         headers = [self.__tr("Select"), self.__tr('Printer (Queue) Name'), self.__tr('Type'), self.__tr('Device URI')]
  1138.  
  1139.         self.RemoveDevicesTableWidget.setColumnCount(len(headers))
  1140.         self.RemoveDevicesTableWidget.setHorizontalHeaderLabels(headers)
  1141.         flags = Qt.ItemIsSelectable | Qt.ItemIsEnabled
  1142.  
  1143.         row = 0
  1144.         for p in self.installed_printers:
  1145.             widget = QCheckBox(self.RemoveDevicesTableWidget)
  1146.             self.connect(widget, SIGNAL("stateChanged(int)"), self.CheckBox_stateChanged)
  1147.             self.RemoveDevicesTableWidget.setCellWidget(row, 0, widget)
  1148.  
  1149.             back_end, is_hp, bus, model, serial, dev_file, host, zc, port = \
  1150.                 device.parseDeviceURI(p.device_uri)
  1151.  
  1152.             if self.device_uri is not None and self.device_uri == p.device_uri:
  1153.                 widget.setCheckState(Qt.Checked)
  1154.  
  1155.             i = QTableWidgetItem(QString(p.name))
  1156.             i.setFlags(flags)
  1157.             i.setData(Qt.UserRole, QVariant(p.name))
  1158.             self.RemoveDevicesTableWidget.setItem(row, 1, i)
  1159.  
  1160.             if back_end == 'hpfax':
  1161.                 typ = self.__tr("Fax")
  1162.             else:
  1163.                 typ = self.__tr("Printer")
  1164.  
  1165.             i = QTableWidgetItem(typ)
  1166.             i.setFlags(flags)
  1167.             self.RemoveDevicesTableWidget.setItem(row, 2, i)
  1168.  
  1169.             i = QTableWidgetItem(QString(p.device_uri))
  1170.             i.setFlags(flags)
  1171.             self.RemoveDevicesTableWidget.setItem(row, 3, i)
  1172.  
  1173.             row += 1
  1174.  
  1175.         self.RemoveDevicesTableWidget.resizeColumnsToContents()
  1176.  
  1177.  
  1178.     def CheckBox_stateChanged(self, i):
  1179.         for row in xrange(self.RemoveDevicesTableWidget.rowCount()):
  1180.             widget = self.RemoveDevicesTableWidget.cellWidget(row, 0)
  1181.             if widget.checkState() == Qt.Checked:
  1182.                 self.NextButton.setEnabled(True)
  1183.                 break
  1184.         else:
  1185.             self.NextButton.setEnabled(False)
  1186.  
  1187.  
  1188.     #
  1189.     # Misc
  1190.     #
  1191.  
  1192.     def NextButton_clicked(self):
  1193.         p = self.StackedWidget.currentIndex()
  1194.         if p == PAGE_DISCOVERY:
  1195.             self.manual = self.ManualGroupBox.isChecked()
  1196.             self.param = unicode(self.ManualParamLineEdit.text())
  1197.             self.jd_port = self.JetDirectSpinBox.value()
  1198.             self.search = unicode(self.SearchLineEdit.text())
  1199.             self.device_desc = int(self.DeviceTypeComboBox.itemData(self.DeviceTypeComboBox.currentIndex()).toInt()[0])
  1200.             self.discovery_method = self.NetworkDiscoveryMethodComboBox.currentIndex()
  1201.  
  1202.             if self.WirelessButton.isChecked():
  1203.                 dlg = WifiSetupDialog(self, device_uri=None, standalone=False)
  1204.                 dlg.exec_()
  1205.  
  1206.                 if dlg.success == SUCCESS_CONNECTED:
  1207.                     self.manual = True
  1208.                     self.param = dlg.hn
  1209.                     self.bus = 'net'
  1210.  
  1211.             self.showDevicesPage()
  1212.  
  1213.         elif p == PAGE_DEVICES:
  1214.             row = self.DevicesTableWidget.currentRow()
  1215.             self.device_uri = self.DevicesTableWidget.item(row, 0).device_uri
  1216.             self.mq = device.queryModelByURI(self.device_uri)
  1217.             back_end, is_hp, bus, model, serial, dev_file, host, zc, port = device.parseDeviceURI(self.device_uri)
  1218.             self.model = models.normalizeModelName(model).lower()
  1219.             self.showAddPrinterPage()
  1220.  
  1221.         elif p == PAGE_ADD_PRINTER:
  1222.             self.print_test_page = self.SendTestPageCheckBox.isChecked()
  1223.             self.print_desc = unicode(self.PrinterDescriptionLineEdit.text()).encode('utf8')
  1224.             self.print_location = unicode(self.PrinterLocationLineEdit.text()).encode('utf8')
  1225.             self.fax_setup = self.SetupFaxGroupBox.isChecked()
  1226.             self.fax_desc = unicode(self.FaxDescriptionLineEdit.text()).encode('utf8')
  1227.             self.fax_location = unicode(self.FaxLocationLineEdit.text()).encode('utf8')
  1228.             self.fax_name_company = unicode(self.NameCompanyLineEdit.text()).encode('utf8')
  1229.             self.fax_number = unicode(self.FaxNumberLineEdit.text()).encode('utf8')
  1230.             self.addPrinter()
  1231.  
  1232.         elif p == PAGE_REMOVE:
  1233.             for row in xrange(self.RemoveDevicesTableWidget.rowCount()):
  1234.                 widget = self.RemoveDevicesTableWidget.cellWidget(row, 0)
  1235.                 if widget.checkState() == Qt.Checked:
  1236.                     item = self.RemoveDevicesTableWidget.item(row, 1)
  1237.                     printer = unicode(item.data(Qt.UserRole).toString()).encode('utf-8')
  1238.                     log.debug("Removing printer: %s" % printer)
  1239.                     cups.delPrinter(printer)
  1240.  
  1241.             self.close()
  1242.  
  1243.         else:
  1244.             log.error("Invalid page!") # shouldn't happen!
  1245.  
  1246.  
  1247.     def BackButton_clicked(self):
  1248.         p = self.StackedWidget.currentIndex()
  1249.         if p == PAGE_DEVICES:
  1250.             self.devices = {}
  1251.             self.showDiscoveryPage()
  1252.  
  1253.         elif p == PAGE_ADD_PRINTER:
  1254.             self.showDevicesPage()
  1255.  
  1256.         else:
  1257.             log.error("Invalid page!") # shouldn't happen!
  1258.  
  1259.  
  1260.     def CancelButton_clicked(self):
  1261.         self.close()
  1262.  
  1263.  
  1264.     def displayPage(self, page):
  1265.         self.StackedWidget.setCurrentIndex(page)
  1266.         self.updateStepText(page)
  1267.  
  1268.  
  1269.     def setNextButton(self, typ=BUTTON_FINISH):
  1270.         if typ == BUTTON_ADD_PRINTER:
  1271.             self.NextButton.setText(self.__tr("Add Printer"))
  1272.         elif typ == BUTTON_NEXT:
  1273.             self.NextButton.setText(self.__tr("Next >"))
  1274.         elif typ == BUTTON_FINISH:
  1275.             self.NextButton.setText(self.__tr("Finish"))
  1276.         elif typ == BUTTON_REMOVE:
  1277.             self.NextButton.setText(self.__tr("Remove"))
  1278.  
  1279.  
  1280.     def updateStepText(self, p):
  1281.         self.StepText.setText(self.__tr("Step %1 of %2").arg(p+1).arg(self.max_page+1))
  1282.  
  1283.  
  1284.     def __tr(self,s,c = None):
  1285.         return qApp.translate("SetupDialog",s,c)
  1286.  
  1287.  
  1288.